#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "networkdebugging.h"

#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QTimer>
#include <QPainter>



MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow),
    serialPort(new QSerialPort(this)),  // 主窗口的串口对象
    udpSocket(nullptr) , // 初始化UDP接收套接字
    writeCntTotal(0),
    readCntTotal(0),
    udpReceiver(nullptr),
    serialStatus(false)
    //udpListenPort(8888)
{
    ui->setupUi(this);
    this-> setLayout(ui->gridLayoutGlobal);

    this->ppage2 = new networkDebugging;//实例化页面2类
    ppage2->setSerialPort(serialPort);    // 传递串口指针
    connect(ui->next,&QPushButton::clicked,[=]
            {
        //所谓切换窗口，其实就是把主窗体隐藏，第二页面显示
        this->hide();//仅仅隐藏，主窗口页面并未释放
        this->ppage2->show();//显示第二个页面
    });

    connect(this->ppage2,&networkDebugging::back,[=]()
    {
        //单独写一个槽函数亦可
        this->ppage2->hide();
        this->show();
    });

    writeCntTotal = 0;
    readCntTotal  = 0;
    serialStatus  =false;
    ui->btnSendContext->setEnabled(false);

    serialPort = new QSerialPort(this);

     QTimer *getSysTimeTimer = new QTimer(this);//更新时间
     connect(getSysTimeTimer,SIGNAL(timeout()),this,SLOT(time_reflash()));
     getSysTimeTimer->start(100);//每隔100毫秒

     timer = new QTimer(this);

    connect(serialPort,&QSerialPort::readyRead,this,&::MainWindow::on_SerialData_readyToRead);

    ui->comboBox_boautrate->setCurrentIndex(6);
    ui->comboBox_databit->setCurrentIndex(3);
    //查找电脑自带的端口
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
    for(QSerialPortInfo serialInfo : serialList)
    {
        qDebug() << serialInfo.portName();
        ui->comboBox_serialNum->addItem(serialInfo.portName());

    }
    initUdpReceiver();  // 调用初始化方法



    // 设置经纬度输入验证器
    latitudeValidator = new QDoubleValidator(minLatitude, maxLatitude, 6, this);
    longitudeValidator = new QDoubleValidator(minLongitude, maxLongitude, 6, this);

    ui->lineEdit_latitude->setValidator(latitudeValidator);
    ui->lineEdit_longtitude->setValidator(longitudeValidator);

}

MainWindow::~MainWindow()
{
    if (udpReceiver)
    {
        udpReceiver->close();
        delete udpReceiver;
    }
    delete ui;
}


// 实现：向串口接收区添加数据
void MainWindow::appendTotextEditRev(const QString &data)
{
    // 确保UI控件名称与实际一致（此处假设串口接收区控件为textEditRev）

    ui->textEditRev->append(data);

    // 可选：滚动到底部，显示最新数据
   // ui->textEditRev->moveCursor(QTextCursor::End);
    /*
    // 可选：同时显示十六进制
    QByteArray hexData = data.toUtf8().toHex(' ');  // 转换为十六进制字符串
    ui->textEditRev->append("[十六进制] " + hexData);
    ui->textEditRev->moveCursor(QTextCursor::End);*/
}

void MainWindow::on_btnCloseOrOpenSerial_clicked()
{
    if(!serialStatus)
    {
    //1. 选择端口号
    serialPort->setPortName(ui->comboBox_serialNum->currentText());
    //2. 配置波特率
    serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
    //3. 配置数据位
    serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_databit->currentText().toUInt()));
    //4. 配置校验位
    switch (ui->comboBox_checkbit->currentIndex())
    {
    case 0:
        serialPort->setParity(QSerialPort::NoParity);//设置流控
        break;
    case 1:
        break;
        serialPort->setParity(QSerialPort::EvenParity);
    case 2:
        serialPort->setParity(QSerialPort::MarkParity);
        break;
    case 3:
        serialPort->setParity(QSerialPort::OddParity);
        break;
    case 4:
        serialPort->setParity(QSerialPort::SpaceParity);
        break;
    //default:
       // serialPort->setParity(QSerialPort::UnknownParity);
       // break;

    }
    //5. 配置停止位
    serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopbit->currentText().toUInt()));
    //6. 流控
    if(ui->comboBox_flowCon->currentText() == "None")
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
    //7.打开串口
    if(serialPort->open(QIODevice::ReadWrite))
    {
        qDebug() << "serial open success";
        ui->comboBox_databit->setEnabled(false);
        ui->comboBox_flowCon->setEnabled(false);
        ui->comboBox_checkbit->setEnabled(false);
        ui->comboBox_stopbit->setEnabled(false);
        ui->comboBox_boautrate->setEnabled(false);
        ui->comboBox_serialNum->setEnabled(false);
        ui->btnCloseOrOpenSerial->setText("关闭串口");
        ui->btnSendContext->setEnabled(true);
        serialStatus = true;
    }
    else
    {
        QMessageBox msgBox;
        msgBox.setWindowTitle("打开串口错误");
        msgBox.setText("打开失败，串口可能被占用或已拔出!");
        msgBox.exec();
    }
    }
    else
    {
        serialPort->close();
        ui->btnCloseOrOpenSerial->setText("打开串口");
        ui->comboBox_databit->setEnabled(true);
        ui->comboBox_flowCon->setEnabled(true);
        ui->comboBox_checkbit->setEnabled(true);
        ui->comboBox_stopbit->setEnabled(true);
        ui->comboBox_boautrate->setEnabled(true);
        ui->comboBox_serialNum->setEnabled(true);
        serialStatus = false;
        ui->btnSendContext->setEnabled(false);

    }
}


//点击发送,历史记录会重复,发送的历史记录，不是接收的历史记录
void MainWindow::on_btnSendContext_clicked()
{
    int writeCnt = 0;
    const char* sendData = ui->lineEditSendContext->text().toStdString().c_str();
    // 新增：同时发送接收区域的数据（以ASCII形式）
   //serialPort->write(ui->textEditRev->toPlainText().toLatin1());

    // 获取接收区文本并转换为ASCII
    QByteArray sendData1 = ui->textEditRev->toPlainText().toLatin1();
    //qDebug() << ui->textEditRev->toPlainText();
    //qDebug() << ui->textEditRev->toPlainText().toLatin1();
    //qDebug() << ui->textEditRev->toPlainText().toUtf8();

    //qDebug() << "原始文本:" << ui->textEditRev->toPlainText();
    qDebug() << "Latin1(ASCII)字节数组:" << sendData1;

    // 遍历输出每个字符的ASCII值和相关信息
    QString binaryString;
    qDebug() << "字符 -> ASCII码 -> 二进制";
    qDebug() << "-------------------------";
    for (char c : sendData1)
    {
        quint8 asciiCode = static_cast<quint8>(c);

        // 将每个ASCII码转换为8位二进制字符串，不足8位前面补0
        QString binStr = QString("%1").arg(asciiCode, 8, 2, QChar('0'));

        // 输出字符、ASCII码和二进制表示
        qDebug() << "'" << c << "' -> " << asciiCode << " -> " << binStr;

        // 对于不可打印字符，额外说明
        if (asciiCode < 32 || asciiCode > 126) {
            qDebug() << "  (不可打印字符，ASCII码：" << asciiCode << ")";
        }

        binaryString += binStr; // 合并所有二进制字符串
    }

    qDebug() << "合并后的二进制序列：" << binaryString;
    // 新增：输出完整的ASCII码序列
    qDebug() << "完整ASCII码序列：";
    for (char c : sendData1) {
        qDebug() << static_cast<quint8>(c) << " ";
    }
    // 输出完整的ASCII码序列（合并成一个字符串）
            qDebug() << "完整ASCII码序列：";
    QString asciiSequence;
    for (char c : sendData1) {
        // 每个ASCII码之间用逗号分隔
        asciiSequence += QString::number(static_cast<quint8>(c)) + ",";
    }
    // 移除最后一个多余的逗号
    if (!asciiSequence.isEmpty()) {
        asciiSequence.chop(1);
    }
    qDebug() << asciiSequence;


    // 发送数据
    qint64 bytesWritten = serialPort->write(sendData1);

    // 输出调试信息
    if (bytesWritten == -1)
    {
        qDebug() << "发送失败：" << serialPort->errorString();
    } else {
        qDebug() << "发送成功，长度：" << bytesWritten << "字节";
        qDebug() << "发送的数据(ASCII)：" << sendData1;
        // 若包含不可见字符，同时输出十六进制以便调试
        qDebug() << "发送的数据(十六进制)：" << sendData1.toHex(' ');
    }

    writeCnt =serialPort->write(sendData);

    qDebug() << "SendOK" << sendData;
    ui->textEditRecord->append(sendData);

    if(writeCnt == -1)//发送失败
    {
        ui->labelSendStatus->setText("SendError!");
    }
    else//发送成功
    {
        writeCntTotal+=writeCnt;
        qDebug() << "SendOK" << sendData;

        ui->labelSendStatus->setText("SendOK!");
        ui->labelSendcnt->setNum(writeCntTotal);//底部标签发送字符

    }
}
//接收数据
void MainWindow::on_SerialData_readyToRead()
{
    QString revMessage = serialPort->readAll();
   // qDebug() << "getMessage:"<< revMessage;
    //ui->textEditRev->append(revMessage);//接收界面

    if (!revMessage.isEmpty())
    {
        qDebug() << "getMessage:"<< revMessage;
        ui->textEditRev->append(revMessage);
        readCntTotal += revMessage.size();
        ui->labelRevcnt->setNum(readCntTotal);//接收到几个字节
    }
}





/*
//点击发送,历史记录不会重复
void MainWindow::on_btnSendContext_clicked()
{
    int writeCnt = 0;
    const char* sendData = ui->lineEditSendContext->text().toStdString().c_str();
    writeCnt =serialPort->write(sendData);

    //qDebug() << "SendOK" << sendData;
   // ui->textEditRecord->append(sendData);

    if(writeCnt == -1)//发送失败
    {
        ui->labelSendStatus->setText("SendError!");
    }
    else//发送成功
    {
        writeCntTotal+=writeCnt;
        qDebug() << "SendOK" << sendData;

        ui->labelSendStatus->setText("SendOK!");
        ui->labelSendcnt->setNum(writeCntTotal);//底部标签发送字符

        if(strcmp(sendData,sendBak.toStdString().c_str()) != 0)//历史记录，使其不重复
        {
            ui->textEditRecord->append(sendData);//更新
            sendBak = QString(sendData);//备份以便更新
        }
    }
}*/


/*
void MainWindow::on_btnCloseOrOpenSerial_clicked(bool checked)
{
    //qDebug() << "IN checked" << checked;
    if(checked){
        //1. 选择端口号
        serialPort->setPortName(ui->comboBox_serialNum->currentText());
        //2. 配置波特率
        serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());
        //3. 配置数据位
        serialPort->setDataBits(QSerialPort::DataBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //4. 配置校验位
        switch (ui->comboBox_checkbit->currentIndex()) {
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            break;
            serialPort->setParity(QSerialPort::EvenParity);
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        }
        //5. 配置停止位
        serialPort->setStopBits(QSerialPort::StopBits(
                                    ui->comboBox_databit->currentText().toUInt()));
        //6. 流控
        if(ui->comboBox_flowCon->currentText() == "None")
            serialPort->setFlowControl(QSerialPort::NoFlowControl);
        //7. 打开串口
        if(serialPort->open(QIODevice::ReadWrite)){
            qDebug() << "serial open success";
            ui->comboBox_databit->setEnabled(false);
            ui->comboBox_flowCon->setEnabled(false);
            ui->comboBox_checkbit->setEnabled(false);
            ui->comboBox_stopbit->setEnabled(false);
            ui->comboBox_boautrate->setEnabled(false);
            ui->comboBox_serialNum->setEnabled(false);
            ui->btnCloseOrOpenSerial->setText("关闭串口");
            ui->btnSendContext->setEnabled(true);
            //serialStatus = true;
        }else
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle("打开串口错误");
            msgBox.setText("打开失败，串口可能被占用，或已拔出");
            msgBox.exec();
        }
    }else{
        serialPort->close();
        ui->btnCloseOrOpenSerial->setText("打开串口");
        ui->comboBox_databit->setEnabled(true);
        ui->comboBox_flowCon->setEnabled(true);
        ui->comboBox_checkbit->setEnabled(true);
        ui->comboBox_stopbit->setEnabled(true);
        ui->comboBox_boautrate->setEnabled(true);
        ui->comboBox_serialNum->setEnabled(true);
       // serialStatus = false;
        ui->btnSendContext->setEnabled(false);
    }
}*/





void MainWindow::on_btnrevClear_clicked()
{
     ui->textEditRev->setText("");
}


void MainWindow::on_btnrevSave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "G:/qt/project/gpsserialport/position.txt",
                                                    tr("Text (*.txt)"));
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        //out << ui->textEditRev->toPlainText();
        out << ui->textEditText->toPlainText();
        file.close();
    }
}


void MainWindow::on_ClearHistory_clicked()
{
    ui->textEditRecord->setText("");
}

void MainWindow::time_reflash()//刷新时间
{
    getSysTime();
    ui->labelCurrentTime->setText(myTime);
}

void MainWindow::getSysTime()
{
    QDateTime currentTime = QDateTime::currentDateTime();

    QDate date = currentTime.date();
    int year = date.year();
    int month = date.month();
    int day = date.day();

    QTime time = currentTime.time();
    int hour = time.hour();
    int minite = time.minute();
    int second = time.second();

   myTime = QString("%1-%2-%3  %4:%5:%6")
                 .arg(year, 2, 10, QChar('0'))
                 .arg(month, 2, 10, QChar('0'))
                 .arg(day, 2, 10, QChar('0'))
                 .arg(hour, 2, 10, QChar('0'))
                 .arg(minite, 2, 10, QChar('0'))
                 .arg(second, 2, 10, QChar('0'));//占位符，十进制
}




// 分析按钮点击事件处理
void MainWindow::on_Analysis_clicked()
{
    // 1. 获取需要解析的数据
    QByteArray serialData = ui->textEditRev->toPlainText().toUtf8();

    // 2. 检查数据是否为空
    if (serialData.isEmpty())
    {
        ui->textEditText->append("没有可解析的数据，请先接收数据或输入内容");
        return;
    }

    // 3. 调用解析函数
    GpsData parsedData = parseSerialData(serialData);

    // 4. 处理解析结果
    if (parsedData.longitude != 0 || parsedData.latitude != 0)
    {
        // 解析成功，合并信息并更新UI显示
        QString info = QString("解析成功:\n 经度: %1\n 纬度: %2\n 时间: %3")
                           .arg(parsedData.longitude, 0, 'f', 5)
                           .arg(parsedData.latitude, 0, 'f', 5)
                           .arg(parsedData.time.toString("yyyy-MM-dd hh:mm:ss"));

        ui->textEditText->setText(info);
    }
    else
    {
        // 解析失败，进行提示
        ui->textEditText->append("解析失败，请检查数据格式");
    }
}

// 解析串口接收到的经纬度数据
GpsData MainWindow::parseSerialData(const QByteArray &data)
{
    GpsData result = {0, 0, QDateTime::currentDateTime(), false};
    QString dataStr = QString::fromUtf8(data);

    // 1. 验证数据格式
    if (!dataStr.startsWith("$AE,") && !dataStr.endsWith("\r\n")) {
        qDebug() << "格式错误：起始或结束标志不正确";
        return result;
    }

    // 2. 提取中间有效数据（改进部分）
    // 先去除首尾的固定字符，再处理可能的控制字符
    QString content = dataStr.mid(4); // 去除前缀"$AE,"
    content = content.left(content.length() - 4); // 去除末尾"\r\n"
    content = content.trimmed(); // 确保没有残留的空白字符

    // 3. 分割经纬度数据
    QStringList parts = content.split(",");
    if (parts.size() != 2) {
        qDebug() << "格式错误：经纬度分割后数量不正确，实际为" << parts.size();
        return result;
    }

    // 4. 转换为数值类型（增加调试信息）
    bool lonOk, latOk;
    double longitude = parts[0].toDouble(&lonOk);
    double latitude = parts[1].toDouble(&latOk);

    // 输出调试信息，查看实际处理的字符串
    qDebug() << "处理的经度字符串:" << parts[0];
    qDebug() << "处理的纬度字符串:" << parts[1];

    // 5. 验证经纬度有效性
    if (!lonOk) {
        qDebug() << "转换错误：经度不是有效数字 -" << parts[0];
        return result;
    }
    if (!latOk) {
        qDebug() << "转换错误：纬度不是有效数字 -" << parts[1];
        return result;
    }

    // 6. 验证经纬度范围
    if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) {
        qDebug() << "范围错误：经纬度超出有效范围";
        return result;
    }

    // 所有验证通过
    result.longitude = longitude;
    result.latitude = latitude;
    result.time = QDateTime::currentDateTime();
    result.isValid = true;

    // 在解析成功后添加代码更新UI
    if (result.isValid) {
        // 将解析得到的经纬度显示到对应的输入框
        ui->lineEdit_latitude->setText(QString::number(result.latitude, 'f', 6));
        ui->lineEdit_longtitude->setText(QString::number(result.longitude, 'f', 6));

        // 由于数据来自串口解析，而非用户输入，可禁用输入框避免手动修改
        ui->lineEdit_latitude->setReadOnly(true);
        ui->lineEdit_longtitude->setReadOnly(true);
    }
    return result;
}

//新增：获取目标IP
QString MainWindow::getTargetIp()
{
    return ui->lineEdit_ip->text().trimmed();  // 假设UI有目标IP输入框
}

//新增：获取目标端口
quint16 MainWindow::getTargetPort()
{
    return ui->lineEdit_com->text().toUInt();  // 假设UI有目标端口输入框
}



void MainWindow::on_SendOutUDP_clicked()
{
    // 1. 获取发送数据
    QString serialData = ui->textEditRev->toPlainText();
    if (serialData.isEmpty())
    {
        QMessageBox::warning(this, "发送失败", "没有可发送的串口数据");
        return;
    }

    // 2. 验证目标IP和端口（关键：目标端口必须与udpListenPort一致才能被本程序接收）
    QString targetIp = getTargetIp(); // 假设从UI获取目标IP（如"127.0.0.1"）
    quint16 targetPort = udpListenPort; // 直接使用监听端口（确保发送到本程序监听的端口）
    // 也可从UI获取，但需保证与监听端口一致，否则接收不到
    // quint16 targetPort = getTargetPort();

    if (targetIp.isEmpty() || targetPort == 0) {
        QMessageBox::warning(this, "参数错误", "请输入正确的目标IP和端口");
        return;
    }

    // 3. 创建UDP发送套接字（临时创建，发送后销毁）
    QUdpSocket *udpSender = new QUdpSocket(this);

    // 4. 转换数据并发送
    QByteArray data = serialData.toUtf8();
    qint64 sendSize = udpSender->writeDatagram(data, QHostAddress(targetIp), targetPort);

    if (sendSize == -1)
    {
         qDebug() << "UDP发送失败: " + udpSender->errorString();
    } else
    {
        qDebug() << QString("UDP发送成功，至 %1:%2，长度: %3字节").arg(targetIp).arg(targetPort).arg(sendSize);
        QString timeStr = QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss] ");
         qDebug() << timeStr + "从串口转发: " + serialData;
        ui->textEditRev->append(timeStr + "发送内容: " + serialData);
        //ui->textEditRec->append(serialData);
        //udpSocket->writeDatagram(serialData.toUtf8(), QHostAddress(targetIp), targetPort);
    }

    // 发送完成后销毁发送套接字
    udpSender->deleteLater();
}


void MainWindow::on_SendOutTCP_clicked()
{
    // 1. 获取需要发送的串口数据
    QString serialData = ui->textEditRev->toPlainText();
    if (serialData.isEmpty())
    {
        QMessageBox::warning(this, "发送失败", "没有可发送的串口数据");
        return;
    }

    // 2. 验证目标IP和端口
    QString targetIp = getTargetIp();
    quint16 targetPort = getTargetPort();
    if (targetIp.isEmpty() || targetPort == 0)
    {
        QMessageBox::warning(this, "参数错误", "请输入正确的目标IP和端口");
        return;
    }

    // 3. 以ASCII形式发送TCP数据
    tcpSocket = new QTcpSocket(this);  // 初始化TCP套接字
    connect(tcpSocket, &QTcpSocket::connected, [=]() {
        QByteArray asciiData = serialData.toUtf8();  // 转换为ASCII兼容的UTF-8
        qint64 sendSize = tcpSocket->write(asciiData);
        if (sendSize == -1) {
            ui->textEditRev->append("TCP发送失败: " + tcpSocket->errorString());
        } else {
            ui->textEditRev->append(QString("TCP发送成功，ASCII数据长度: %1字节").arg(sendSize));
        }
        tcpSocket->flush();
        //tcpSocket->disconnectFromHost();  // 发送完成后断开连接
    });

    connect(tcpSocket, &QTcpSocket::errorOccurred, [=](QAbstractSocket::SocketError error)
    {
        ui->textEditRev->append("TCP连接失败: " + tcpSocket->errorString());
    });

    // 连接到目标服务器
    tcpSocket->connectToHost(targetIp, targetPort);
}

/*
void MainWindow::sendGpsDataAsAscii(const GpsData &data, QSerialPort* targetSerial)
{
    if (!data.isValid)
    {
        QMessageBox::warning(this, "发送失败", "GPS数据无效，无法发送");
        return;
    }

    // 1. 构建ASCII格式数据包（NMEA格式）
    QString baseData = QString("GPGGA,%1,%2,%3")
                           .arg(data.longitude, 0, 'f', 6)  // 经度，保留6位小数
                           .arg(data.latitude, 0, 'f', 6)   // 纬度，保留6位小数
                           .arg(data.time.toString("HHmmss.zzz"));   // 时间

    // 计算校验和并完成数据包
    quint8 checksum = calculateChecksum(baseData);
    QString asciiData = QString("$%1*%2\r\n")
                            .arg(baseData)
                            .arg(checksum, 2, 16, QLatin1Char('0')).toUpper();  // 校验和转为2位十六进制

    QByteArray packet = asciiData.toLatin1();  // 转换为纯ASCII字符

    // 2. 显示发送的ASCII数据包内容
    QString packetInfo = QString("发送的GPS ASCII数据包详情：\n") +
                         QString("总长度：%1字节\n").arg(packet.size()) +
                         QString("ASCII内容：%1").arg(asciiData);
    qDebug() << packetInfo;
    ui->textEditRecord->append("[GPS发送] " + asciiData);

    // 3. 检查目标串口是否有效且已打开
    if (!targetSerial || !targetSerial->isOpen())
    {
        QMessageBox::warning(this, "发送失败", "目标串口未打开或无效");
        return;
    }

    // 4. 通过串口发送ASCII数据
    qint64 bytesWritten = targetSerial->write(packet);

    if (bytesWritten == -1)
    {
        QString errorMsg = QString("GPS数据发送失败: %1").arg(targetSerial->errorString());
        qDebug() << errorMsg;
        ui->textEditRecord->append("[错误] " + errorMsg);
    }
    else
    {
        QString successMsg = QString("GPS ASCII数据发送成功，长度：%1字节").arg(bytesWritten);
        qDebug() << successMsg;
        ui->textEditRecord->append("[成功] " + successMsg);

        // 更新发送计数
        writeCntTotal += bytesWritten;
        ui->labelSendcnt->setNum(writeCntTotal);
    }
}

// 辅助函数：计算校验和（用于ASCII数据包）
quint8 calculateChecksum(const QString &data)
{
    quint8 checksum = 0;
    for (int i = 0; i < data.length(); ++i)
    {
        checksum ^= data.at(i).toLatin1();  // 异或校验
    }
    return checksum;
}*/

    //初始化UDP接收：创建套接字、绑定端口、连接接收信号
void MainWindow::initUdpReceiver()
{
    // 若已存在则先关闭，避免重复创建
    if (udpReceiver) {
        udpReceiver->close();
        delete udpReceiver;
    }
    // 创建UDP接收套接字（作为类成员，长期存在以持续监听）
    udpReceiver = new QUdpSocket(this);

    // 绑定本地端口（关键步骤！UDP必须绑定端口才能接收数据）
    // QHostAddress::Any表示监听所有网络接口（本地/局域网/公网）
    bool bindSuccess = udpReceiver->bind(QHostAddress::Any, udpListenPort);
    if (!bindSuccess) {
       qDebug () <<"UDP接收初始化失败：无法绑定端口 " + QString::number(udpListenPort)
                                                                         + "，原因：" + udpReceiver->errorString();
        return;
    }

    // 连接"有数据到达"信号到接收处理函数（核心：数据到达时触发）
    connect(udpReceiver, &QUdpSocket::readyRead, this, &MainWindow::onUdpDataReceived);

   qDebug () << "UDP接收已启动，监听端口：" + QString::number(udpListenPort);
}


// UDP数据接收处理函数（数据到达时被调用）
void MainWindow::onUdpDataReceived()
{
    // 循环读取所有待处理的数据报（可能同时到达多个）
    while (udpReceiver->hasPendingDatagrams()) {
        QByteArray datagram;  // 存储接收的数据
        QHostAddress senderIp; // 发送方IP
        quint16 senderPort;    // 发送方端口

        // 调整缓冲区大小以匹配待接收数据的长度
        datagram.resize(udpReceiver->pendingDatagramSize());

        // 读取数据报（获取数据、发送方IP和端口）
        qint64 bytesReceived = udpReceiver->readDatagram(
            datagram.data(),    // 数据缓冲区
            datagram.size(),    // 缓冲区大小
            &senderIp,          // 输出：发送方IP
            &senderPort         // 输出：发送方端口
            );

        if (bytesReceived != -1) {
            // 将接收的数据显示到"网口接收区域"（假设用textEditRev）
            //ui->textEditRev->append("------------------------------");
           qDebug () << "UDP接收成功（来自 " + senderIp.toString() + ":" + QString::number(senderPort) + "）";
           qDebug () << "接收内容：" + QString(datagram); // 转换为字符串显示
           qDebug () << "接收长度：" + QString::number(bytesReceived) + "字节";
        } else {
           qDebug () << ("UDP接收失败：" + udpReceiver->errorString());
        }
    }
}


void MainWindow::on_AddPoint_clicked()
{
    // 获取经纬度输入
    double latitude = ui->lineEdit_latitude->text().toDouble();
    double longitude = ui->lineEdit_longtitude->text().toDouble();

    // 添加到坐标列表
    coordinates.append(QPointF(latitude, longitude));

    // 更新显示
    update();

    // 状态栏显示
    statusBar()->showMessage(QString("添加点: 纬度 = %1, 经度 = %2").arg(latitude).arg(longitude), 3000);
}


void MainWindow::on_ClearPoint_clicked()
{
    // 清空坐标列表
    coordinates.clear();

    // 更新显示
    update();

    // 状态栏显示
    statusBar()->showMessage("已清除所有点", 2000);
}



QPointF MainWindow::latLngToScreen(const QPointF &latLng)
{
    QRect drawArea = ui->frame->geometry();
    drawArea.moveTopLeft(ui->frame->mapToGlobal(QPoint(0, 0)));
    drawArea = drawArea.translated(-this->geometry().topLeft());

    // 调整边界，留出一些边距
    drawArea.adjust(10, 10, -10, -10);

    double x = drawArea.left() +
               (latLng.y() - minLongitude) * drawArea.width() / (maxLongitude - minLongitude);
    double y = drawArea.bottom() -
               (latLng.x() - minLatitude) * drawArea.height() / (maxLatitude - minLatitude);

    return QPointF(x, y);
}



void MainWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 获取绘图区域
    QRect drawArea = ui->frame->geometry();
    drawArea.moveTopLeft(ui->frame->mapToGlobal(QPoint(0, 0)));
    drawArea = drawArea.translated(-this->geometry().topLeft());

    // 绘制背景
    //painter.fillRect(drawArea, Qt::white);

    // 绘制网格和坐标轴
    painter.setPen(QPen(Qt::lightGray, 1));

    // 计算网格间距
    int gridCount = 5;
    int gridWidth = drawArea.width() / gridCount;
    int gridHeight = drawArea.height() / gridCount;

    // 绘制垂直线
    for (int i = 0; i <= gridCount; ++i) {
        int x = drawArea.left() + i * gridWidth;
        painter.drawLine(x, drawArea.top(), x, drawArea.bottom());

        // 绘制经度标签
        double longitude = minLongitude + (maxLongitude - minLongitude) * i / gridCount;
        painter.drawText(x -20, drawArea.bottom() + 20, QString::number(longitude, 'f', 2));
    }

    // 绘制水平线
    for (int i = 0; i <= gridCount; ++i) {
        int y = drawArea.top() + i * gridHeight;
        painter.drawLine(drawArea.left(), y, drawArea.right(), y);

        // 绘制纬度标签
        double latitude = maxLatitude - (maxLatitude - minLatitude) * i / gridCount;
        painter.drawText(drawArea.left() - 40, y + 5, QString::number(latitude, 'f', 2));
    }

    // 绘制坐标轴
    painter.setPen(QPen(Qt::black, 2));
    painter.drawLine(drawArea.left(), drawArea.top(), drawArea.left(), drawArea.bottom());  // Y轴
    painter.drawLine(drawArea.left(), drawArea.bottom(), drawArea.right(), drawArea.bottom());  // X轴

    // 绘制所有坐标点
    painter.setPen(QPen(Qt::red, 5, Qt::SolidLine, Qt::RoundCap));
    for (const auto &coord : coordinates) {
        QPointF screenPos = latLngToScreen(coord);
        painter.drawPoint(screenPos);
    }

    // 绘制图例
    painter.setPen(QPen(Qt::black, 1));
    painter.drawText(drawArea.left()-30 , drawArea.top() - 10, "经度范围: " +
                                                                    QString::number(minLongitude, 'f', 2) + " - " +
                                                                    QString::number(maxLongitude, 'f', 2));
    painter.drawText(drawArea.left() + 140, drawArea.top() - 10, "纬度范围: " +
                                                                     QString::number(minLatitude, 'f', 2) + " - " +
                                                                     QString::number(maxLatitude, 'f', 2));
}

